# CRYPTO

# d3qcg

from Crypto.Util.number import *
import random
from random import randint
from gmpy2 import *
from secret import flag
import hashlib
assert b'd3ctf' in flag
Bits = 512
UnKnownBits = 146
class QCG():
    def __init__(self,bit_length):
        p = getPrime(bit_length)
        a = randint(0,p)
        c = randint(0,p)
        self._key = {'a':a,'c':c,'p':p}
        self.secret = randint(0,p)
        self.high = []
    def Qnext(self,num):
        return ((self._key['a'])*num**2+self._key['c'])%self._key['p']
    
    def hint(self):
        num = self.secret
        for i in range(2):
            num = self.Qnext(num)
            self.high.append(num>>UnKnownBits)
    def get_key(self):
        return self._key
    def get_hint(self):
        return self.high
Q1 = QCG(Bits)
print(Q1.get_key())
#{'a': 3591518680290719943596137190796366296374484536382380061852237064647969442581391967815457547858969187198898670115651116598727939742165753798804458359397101, 'c': 6996824752943994631802515921125382520044917095172009220000813718617441355767447428067985103926211738826304567400243131010272198095205381950589038817395833, 'p': 7386537185240346459857715381835501419533088465984777861268951891482072249822526223542514664598394978163933836402581547418821954407062640385756448408431347}
Q1.hint()
print(Q1.get_hint())
#[67523583999102391286646648674827012089888650576715333147417362919706349137337570430286202361838682309142789833, 70007105679729967877791601360700732661124470473944792680253826569739619391572400148455527621676313801799318422]
enc = bytes_to_long(hashlib.sha512(b'%d'%(secret)).digest())^bytes_to_long(flag)
print(enc)
# 6176615302812247165125832378994890837952704874849571780971393318502417187945089718911116370840334873574762045429920150244413817389304969294624001945527125

我们需要求 secret

secret 有下列关系

a*secret*secret +c mod p = x0

a*x0*x0+c mod p = x1

而我们知道了 x0 和 x1 的高位,第一时间就想到了 coppersmith

之前做到过类似的题目 ctfshow 吃鸡杯里的 Cop!Run!!

直接用模板改一下

from tqdm import tqdm
import itertools
def small_roots(f, bounds, m=1, d=None):
    if not d:
        d = f.degree()
    R = f.base_ring()
    N = R.cardinality()
    f /= f.coefficients().pop(0)
    f = f.change_ring(ZZ)
    G = Sequence([], f.parent())
    for i in range(m + 1):
        base = N ^ (m - i) * f ^ i
        for shifts in itertools.product(range(d), repeat=f.nvariables()):
            g = base * prod(map(power, f.variables(), shifts))
            G.append(g)
    B, monomials = G.coefficient_matrix()
    monomials = vector(monomials)
    factors = [monomial(*bounds) for monomial in monomials]
    for i, factor in enumerate(factors):
        B.rescale_col(i, factor)
    B = B.dense_matrix().LLL()
    B = B.change_ring(QQ)
    for i, factor in enumerate(factors):
        B.rescale_col(i, 1 / factor)
    H = Sequence([], f.parent().change_ring(QQ))
    for h in filter(None, B * monomials):
        H.append(h)
        I = H.ideal()
        if I.dimension() == -1:
            H.pop()
        elif I.dimension() == 0:
            roots = []
            for root in I.variety(ring=ZZ):
                root = tuple(R(root[var]) for var in f.variables())
                roots.append(root)
            return roots
    return []
from Crypto.Util.number import long_to_bytes
a=3591518680290719943596137190796366296374484536382380061852237064647969442581391967815457547858969187198898670115651116598727939742165753798804458359397101
c=6996824752943994631802515921125382520044917095172009220000813718617441355767447428067985103926211738826304567400243131010272198095205381950589038817395833
p=7386537185240346459857715381835501419533088465984777861268951891482072249822526223542514664598394978163933836402581547418821954407062640385756448408431347
Fp=Zmod(p)
x_=[67523583999102391286646648674827012089888650576715333147417362919706349137337570430286202361838682309142789833, 70007105679729967877791601360700732661124470473944792680253826569739619391572400148455527621676313801799318422]
PR.<t> = PolynomialRing(Fp)
f = a*t*t+c
PR.<k0, k1> = PolynomialRing(Fp)
s = f(x_[0]*2^146 + k0)-x_[1]*2^146-k1
roots = small_roots(s, (2^146,2^146),m=3,d=6) #这里的 m 和 d 不知道是啥意思,打比赛的时候用了 d=2 然后就没跑出来
x=6023304966622247460261427847144394818572943247946434323275721792843243938440324294324349326166203828252327046668948034768905493329350113405677812338671880
PR.<x0>=PolynomialRing(Fp)
s=f(x0)-x
s.roots()
import hashlib
from Crypto.Util.number import *
secret=[4041175780036883478815867467461047550933982405318965631484489156717330002773568568536902190010839138410185231519872805730895806870604072973967270279033142,
3345361405203462981041847914374453868599106060665812229784462734764742247048957655005612474587555839753748604882708741687926147536458567411789178129398205]
c=[]
for i in range(2):
    c.append(bytes_to_long(hashlib.sha512(b'%d'%(secret[i])).digest()))
enc=6176615302812247165125832378994890837952704874849571780971393318502417187945089718911116370840334873574762045429920150244413817389304969294624001945527125
for i in range(2):
    print(long_to_bytes(enc^c[i]))

# d3bug

比赛时出了 LF5R 后面选择爆破没爆出来┗|`O′|┛

from Crypto.Util.number import *
from secret import flag
assert flag.startswith("D3CTF{")
assert flag.endswith("}")
message = bytes_to_long(flag[6:-1])
assert message < 2**64
mask = 0b1010010000001000000010001001010010100100000010000000100010010100
def lfsr_MyCode(R,mask):
    output = (R << 1) & 0xffffffffffffffff
    i = (R ^ mask) & 0xffffffffffffffff
    lastbit = 0
    while i != 0:
        lastbit ^= (i & 1)
        i = i>>1
    output ^= lastbit
    return (output,lastbit)
def lfsr_CopiedfromInternet(R,mask):
    output = (R << 1) & 0xffffffffffffffff
    i = (R & mask) & 0xffffffffffffffff
    lastbit = 0
    while i != 0:
        lastbit ^= (i & 1)
        i = i>>1
    output ^= lastbit
    return (output,lastbit)
f=open("standardResult","w")
R=message
for i in range(35):
    (R, out) = lfsr_CopiedfromInternet(R,mask)
    f.write(str(out))
f.close()
f=open("myResult","w")
R=message
for i in range(35):
    (R, out) = lfsr_MyCode(R,mask)
    f.write(str(out))
f.close()
#Why are the results always different?!!
#Can you help me debug my code? QAQ
#myresult 00100110001000110001101010101001001
#standard 01111101111010111000010010111001101

考点肯定是 lfsr 了

但是他这里有一个坑 他只给了前 35 位,所以我只出了高位

看一下大佬解法

A = matrix(GF(2),70,64)
T1 = matrix(GF(2),64,64)
T2 = matrix(GF(2),64,64)
for i in range(63):
   T1[i,i+1] = 1
   T2[i,i+1] = 1
T1[-1] = [int(i) for i in
'1010010000001000000010001001010010100100000010000000100010010100']
T2[-1] = [1]*64
E1 = T1^64
E2 = T2^64
r1 = '01111101111010111000010010111001101'
r2 = '00100110001000110001101010101001001'
for i in range(35):
 A[i] = E1[i]
 A[i+35] = E2[i]
 b = [int(i) for i in r1+r2]
ans = A.solve_right(b)
print(ans)
flag = 0
for i in ans:
    flag = flag*2+int(i)
print(int.to_bytes(int(flag),8,'big'))
#D3CTF{LF5Rsuk!}

看不太懂啊┭┮﹏┭┮

# d3factor

from Crypto.Util.number import bytes_to_long, getPrime
from secret import msg
from sympy import nextprime
from gmpy2 import invert
from hashlib import md5
flag = 'd3ctf{'+md5(msg).hexdigest()+'}'
p = getPrime(256)
q = getPrime(256)
assert p > q
n = p * q
e = 0x10001
m = bytes_to_long(msg)
c = pow(m, e, n)
N = pow(p, 7) * q
phi = pow(p, 6) * (p - 1) * (q - 1)
d1 = getPrime(2000)
d2 = nextprime(d1 + getPrime(1000))
e1 = invert(d1, phi)
e2 = invert(d2, phi)
print(f'c = {c}')
print(f'N = {N}')
print(f'e1 = {e1}')
print(f'e2 = {e2}')
'''
c = 2420624631315473673388732074340410215657378096737020976722603529598864338532404224879219059105950005655100728361198499550862405660043591919681568611707967
N = 1476751427633071977599571983301151063258376731102955975364111147037204614220376883752032253407881568290520059515340434632858734689439268479399482315506043425541162646523388437842149125178447800616137044219916586942207838674001004007237861470176454543718752182312318068466051713087927370670177514666860822341380494154077020472814706123209865769048722380888175401791873273850281384147394075054950169002165357490796510950852631287689747360436384163758289159710264469722036320819123313773301072777844457895388797742631541101152819089150281489897683508400098693808473542212963868834485233858128220055727804326451310080791
e1 = 425735006018518321920113858371691046233291394270779139216531379266829453665704656868245884309574741300746121946724344532456337490492263690989727904837374279175606623404025598533405400677329916633307585813849635071097268989906426771864410852556381279117588496262787146588414873723983855041415476840445850171457530977221981125006107741100779529209163446405585696682186452013669643507275620439492021019544922913941472624874102604249376990616323884331293660116156782891935217575308895791623826306100692059131945495084654854521834016181452508329430102813663713333608459898915361745215871305547069325129687311358338082029
e2 = 1004512650658647383814190582513307789549094672255033373245432814519573537648997991452158231923692387604945039180687417026069655569594454408690445879849410118502279459189421806132654131287284719070037134752526923855821229397612868419416851456578505341237256609343187666849045678291935806441844686439591365338539029504178066823886051731466788474438373839803448380498800384597878814991008672054436093542513518012957106825842251155935855375353004898840663429274565622024673235081082222394015174831078190299524112112571718817712276118850981261489528540025810396786605197437842655180663611669918785635193552649262904644919
'''

解法

from Crypto.Util.number import *
from hashlib import *
c = 2420624631315473673388732074340410215657378096737020976722603529598864338532404224879219059105950005655100728361198499550862405660043591919681568611707967
N = 1476751427633071977599571983301151063258376731102955975364111147037204614220376883752032253407881568290520059515340434632858734689439268479399482315506043425541162646523388437842149125178447800616137044219916586942207838674001004007237861470176454543718752182312318068466051713087927370670177514666860822341380494154077020472814706123209865769048722380888175401791873273850281384147394075054950169002165357490796510950852631287689747360436384163758289159710264469722036320819123313773301072777844457895388797742631541101152819089150281489897683508400098693808473542212963868834485233858128220055727804326451310080791
e1 = 425735006018518321920113858371691046233291394270779139216531379266829453665704656868245884309574741300746121946724344532456337490492263690989727904837374279175606623404025598533405400677329916633307585813849635071097268989906426771864410852556381279117588496262787146588414873723983855041415476840445850171457530977221981125006107741100779529209163446405585696682186452013669643507275620439492021019544922913941472624874102604249376990616323884331293660116156782891935217575308895791623826306100692059131945495084654854521834016181452508329430102813663713333608459898915361745215871305547069325129687311358338082029
e2 = 1004512650658647383814190582513307789549094672255033373245432814519573537648997991452158231923692387604945039180687417026069655569594454408690445879849410118502279459189421806132654131287284719070037134752526923855821229397612868419416851456578505341237256609343187666849045678291935806441844686439591365338539029504178066823886051731466788474438373839803448380498800384597878814991008672054436093542513518012957106825842251155935855375353004898840663429274565622024673235081082222394015174831078190299524112112571718817712276118850981261489528540025810396786605197437842655180663611669918785635193552649262904644919
P.<x> = PolynomialRing(Zmod(N))
f = e1*e2*x - (e1-e2)
f = f.monic()
res = int(f.small_roots(X=2**1000, beta=0.75)[0])
p = int(gcd(int(f(res)), N))
p = 81911394167511996830305370213894554209992159667974516868378702592733037962549
q = N // p**7
assert p ** 7 * q == N
phi = (p-1)*(q-1)
d = inverse(65537, phi)
m = int(pow(c, d, p*q))
msg = long_to_bytes(m)
print(msg)
flag = 'd3ctf{'+md5(msg).hexdigest()+'}'
print(flag)
更新于 阅读次数